import java.util.ArrayList;

class mage {
	public int isTopBottom = 0;
	public double value = 0;

}

public class MageCalc {

	public double getSD(ArrayList list) {
		if (list.size() > 1) {
			int m = list.size();
			double sum = 0;
			for (int i = 0; i < m; i++) {// 求和
				sum += Double.parseDouble(list.get(i).toString());
			}
			double dAve = sum / m;// 求平均值
			double dVar = 0;
			for (int i = 0; i < m; i++) {// 求方差
				dVar += (Double.parseDouble(list.get(i).toString()) - dAve)
						* (Double.parseDouble(list.get(i).toString()) - dAve);
			}
			return Math.sqrt(dVar / m);
		} else {
			return 0;
		}

	}

	public double getAverage(ArrayList list) {
		double sum = 0;
		if (list.size() > 0) {
			for (int i = 0; i < list.size(); i++) {
				sum += Double.parseDouble(list.get(i).toString());
			}
			return sum / list.size();
		} else {
			return 0;
		}

	}

	public double getMaxValue(ArrayList sampleList) {
		try {
			double maxDevation = 0.0;
			int totalCount = sampleList.size();
			if (totalCount >= 1) {
				double max = Double.parseDouble(sampleList.get(0).toString());
				for (int i = 0; i < totalCount; i++) {
					double temp = Double.parseDouble(sampleList.get(i).toString());
					if (temp > max) {
						max = temp;
					}
				}
				maxDevation = max;
			}
			return maxDevation;
		} catch (Exception ex) {
			throw ex;
		}
	}

	public ArrayList Mage2Double(ArrayList list) {
		ArrayList filterList = new java.util.ArrayList();
		for (int i = 0; i < list.size(); i++) {
			filterList.add(((mage) list.get(i)).value);
		}
		return filterList;
	}

	/// <summary>
	/// 去除相邻重复数据。
	/// </summary>
	public static ArrayList filterStep1(ArrayList list) {
		ArrayList filterList = new java.util.ArrayList();
		for (int i = 0; i < list.size(); i++) {
			// 最后一条数据
			if (i == (list.size() - 1)) {
				filterList.add(list.get(i));
			} else {
				if (Double.parseDouble(list.get(i).toString()) != Double.parseDouble(list.get(i + 1).toString())) {
					filterList.add(list.get(i));
				}
			}

		}
		return filterList;
	}

	/// <summary>
	/// 对SG数据进行预处理，获取极大值和极小值。
	/// </summary>
	public ArrayList filterStep2(ArrayList list) {
		ArrayList filterListStep1 = new java.util.ArrayList();
		for (int i = 0; i < list.size(); i++) {
			// 去除相邻重复数据
			filterListStep1 = filterStep1(list);
		}

		mage wk_mage;
		ArrayList filterListStep2 = new java.util.ArrayList();
		ArrayList filterListStep2Print = new java.util.ArrayList();
		for (int i = 0; i < filterListStep1.size(); i++) {
			// 第一个点
			if (i == 0) {
				// Double.parseDoubleDouble
				wk_mage = new mage();
				if (Double.parseDouble(filterListStep1.get(i).toString()) < Double
						.parseDouble(filterListStep1.get(i + 1).toString())) {
					wk_mage.isTopBottom = 0;
				} else {
					wk_mage.isTopBottom = 1;
				}
				wk_mage.value = Double.parseDouble(filterListStep1.get(i).toString());
				filterListStep2Print.add(filterListStep1.get(i));
				filterListStep2.add(wk_mage);
				continue;
			}
			// 最后一个点
			// if (((filterListStep1.size() % 2 == 0) && (i + 1 ==
			// filterListStep1.size())) || ((filterListStep1.size() % 2 != 0) &&
			// (i == filterListStep1.size())))
			if (i == (filterListStep1.size() - 1)) {
				wk_mage = new mage();
				if (Double.parseDouble(filterListStep1.get(i - 1).toString()) < Double
						.parseDouble(filterListStep1.get(i).toString())) {
					wk_mage.isTopBottom = 1;
				} else {
					wk_mage.isTopBottom = 0;
				}
				wk_mage.value = Double.parseDouble(filterListStep1.get(i).toString());
				filterListStep2Print.add(filterListStep1.get(i));
				filterListStep2.add(wk_mage);
			} else {
				wk_mage = new mage();
				if (Double.parseDouble(filterListStep1.get(i - 1).toString()) < Double
						.parseDouble(filterListStep1.get(i).toString())
						&& Double.parseDouble(filterListStep1.get(i).toString()) > Double
								.parseDouble(filterListStep1.get(i + 1).toString())) {
					wk_mage.isTopBottom = 1;
					wk_mage.value = Double.parseDouble(filterListStep1.get(i).toString());
					filterListStep2Print.add(filterListStep1.get(i));
					filterListStep2.add(wk_mage);
					// System.Console.Write("极大值点:" + list.get(i));

				}
				if (Double.parseDouble(filterListStep1.get(i - 1).toString()) > Double
						.parseDouble(filterListStep1.get(i).toString())
						&& Double.parseDouble(filterListStep1.get(i).toString()) < Double
								.parseDouble(filterListStep1.get(i + 1).toString())) {
					wk_mage.isTopBottom = 0;
					wk_mage.value = Double.parseDouble(filterListStep1.get(i).toString());
					filterListStep2Print.add(filterListStep1.get(i));
					filterListStep2.add(wk_mage);
					// System.Console.Write("极小值点:" + list.get(i));
				}
			}
		}
		return filterListStep2;
	}

	// step3
	public ArrayList filterStep3(ArrayList list, double SD) {
		ArrayList filterList = new java.util.ArrayList();

		double leftValue = 0.0d;
		double rightValue = 0.0d;
		ArrayList removeBottomList = new java.util.ArrayList();
		ArrayList removeTopList = new java.util.ArrayList();
		ArrayList removedBottomMageList = new java.util.ArrayList();

		ArrayList removedBottomMageListPrint = new java.util.ArrayList();
		// 找出所有无效极小值点
		for (int i = 1; i < list.size() - 1; i++) {
			// 第一个点为极大值点，跳过
			if ((i == 1) && (((mage) list.get(i - 1)).isTopBottom == 1)) {
				continue;
			} else if ((i > 1) && (((mage) list.get(i)).isTopBottom == 1)) {
				leftValue = Math.abs(((mage) list.get(i)).value - ((mage) list.get(i - 1)).value);
				rightValue = Math.abs(((mage) list.get(i)).value - ((mage) list.get(i + 1)).value);
				if (leftValue >= rightValue) {
					if (rightValue < SD) {
						removeBottomList.add(i + 1);
					}
				} else {
					if (leftValue < SD) {
						removeBottomList.add(i - 1);
					}
				}
			}
		}
		// 删除所有无效极小值点
		// 去除重复坐标
		removeBottomList = filterStep1(removeBottomList);
		for (int i = 0; i < list.size(); i++) {
			Boolean deleted = false;
			for (int j = 0; j < removeBottomList.size(); j++) {
				if ((int) removeBottomList.get(j) == i) {
					deleted = true;
				}
			}
			if (!deleted) {
				removedBottomMageList.add(list.get(i));
				removedBottomMageListPrint.add(((mage) list.get(i)).value);
			}
		}
		list = removedBottomMageList;

		// 保留相邻极小值点中最大的极大值点
		for (int i = 0; i < list.size(); i++) {
			// 第一个点加入
			if (i == 0 && ((mage) list.get(i)).isTopBottom == 0) {
				filterList.add(Math.round(((mage) list.get(i)).value));
			} else {
				if (((mage) list.get(i)).isTopBottom == 1) {
					removeTopList.add(list.get(i));
					// 最后一条数据且为 极大值
					if (i == (list.size() - 1)) {
						filterList.add(Math.round(getMaxValue(Mage2Double(removeTopList))));
					}
				} else {
					// 添加两极小值点间最大的极大值点
					if (removeTopList.size() > 0) {
						filterList.add(Math.round(getMaxValue(Mage2Double(removeTopList))));
						removeTopList.clear();
					}
					// 添加极小值点
					filterList.add(Math.round(((mage) list.get(i)).value));
				}
			}
		}
		return filterList;
	}

	public double Calc_MAGE(ArrayList list, double SD, String unit) {
		double mgdl_To_mmoll = 18.016;
		// 采样点
		int sample_Count = 216;// 288 的75% 可以进行mage值计算
		// rate 比率，通常为1个标准差，可以设置0.5倍，2倍等其他比率
		double mage_rate = 1.0;

		// 返回的mage值
		double mageValue = 0.0d;
		// 标准差
		double standard_Dev = SD;

		double leftValue = 0.0d;
		double rightValue = 0.0d;
		int mage_type = 1;// 1 波谷，-1 波峰
		int mage_direction = 1; // 1 下降支，-1 上升支
		Boolean mage_flg = false;// 寻找age计算方向开关

		// standard_Dev = SD;
		// 统计有效的日内mage点
		ArrayList mageList = new ArrayList();
		// 统计点数不足216个时，直接返回"-"
		if (list.size() < sample_Count) {
			mageValue = 0.0d;
		} else {
			// 过滤无效数据点
			list = filterStep3(filterStep2(list), standard_Dev);

			// Math.round(getAverage(mageList));
			if (list.size() > 2) {
				// 计算标准差
				// standard_Dev = Math.round(Math.Sqrt(array.Sum(d => Math.Pow(d
				// - array.Average(), 2)) / array.Count()-1), 2);

				for (int i = 1; i <= list.size(); i += 1) {
					if (i >= (list.size() - 1)) {
						break;
					}
					// 最后一个SG点，退出循环
					if (((list.size() % 2 == 0) && (i + 1 == list.size()))
							|| ((list.size() % 2 != 0) && (i == list.size() - 1))) {
						break;
					}
					leftValue = Math.abs(Double.parseDouble(list.get(i).toString())
							- Double.parseDouble(list.get(i - 1).toString()));
					rightValue = Math.abs(Double.parseDouble(list.get(i).toString())
							- Double.parseDouble(list.get(i + 1).toString()));
					// 计算一个SG点左右两边的变动幅度，同时大于标准差才是有效mage点
					if ((leftValue > mage_rate * standard_Dev) && (rightValue > mage_rate * standard_Dev)) {
						// 判断mage曲线的tpye是波峰还是波谷
						if (Double.parseDouble(list.get(i - 1).toString()) < Double
								.parseDouble(list.get(i).toString())) {
							// 波峰
							mage_type = -1;
						} else {
							// 波谷
							mage_type = 1;
						}
						// 如果是一个有效mage点，则取左右两边变动幅度的最大值作为mage值
						// 判断上升支，下降支
						if (!mage_flg) {
							if (leftValue > rightValue) {
								if (Double.parseDouble(list.get(i).toString()) < Double
										.parseDouble(list.get(i - 1).toString())) {
									// 下降支
									mage_direction = 1;
								} else {
									// 上升支
									mage_direction = -1;
								}
							} else {
								if (Double.parseDouble(list.get(i).toString()) > Double
										.parseDouble(list.get(i + 1).toString())) {
									// 下降支
									mage_direction = 1;
								} else {
									// 上升支
									mage_direction = -1;
								}
							}
							mageList.add(Math.max(leftValue, rightValue));
							// 已加入magelist后，跳过i+1的点，该点信息已经使用过
							i++;
							// LogManager.WriteLog(LogManager.logFileType.Trace,
							// "first age value ： " + mageList.toString());
							// 已经找到age计算方向，开关关闭
							mage_flg = true;
						} else {
							if (mage_type * mage_direction == 1) {

								// 波谷态，下降支或波峰态，上升支
								if (leftValue >= standard_Dev) {
									mageList.add(leftValue);
									// 已加入magelist后，跳过i+1的点，该点信息已经使用过
									i++;
								}
							} else {
								// 波谷态，上升支或或波峰态，下降支
								if (rightValue >= standard_Dev) {
									mageList.add(rightValue);
									i++;
								}

							}
							// LogManager.WriteLog(LogManager.logFileType.Trace,
							// "age value ： " + mageList.toString());
						}

					}
				}
				// 求日间age的均值->mage
				if (mageList.size() > 0) {
					mageValue = Math.round(getAverage(mageList));
				} else {
					mageValue = 0.0d;
				}
			} else {
				mageValue = 0.0d;
			}
		}
		// 单位换算
		// MG_DL or MMOL_L

		if (unit == "MG_DL") {
			mageValue = Math.round(mageValue * mgdl_To_mmoll);
		}
		return mageValue;
	}

}
